setScreenMetrics(1080, 2400);
auto.waitFor(); //
FloatyUtil(); //=悬浮窗加载===
init();
打开微信页面();
showFLog("等待加载二维码~|或个人中心");
findAndClick("使用完整.*");
findAndClick("继续访问");
findAndClick("开始阅读");
let 长按二维码 = widgetGetOne("长按二维码.*");
if (长按二维码) {
  press(500, 长按二维码.bounds().top - 200, 2000);
  sleep(1000);
  findAndClick("识别图中的二维码");
  循环30();
} else {
  showFLog("没查询到二维码，退出");
}
退出();

//==============
function 循环30() {
  for (let i = 0; i < 30; i++) {
    sleep(6000);
    if (widgetGetOne("文件传输助手")) {
      back();
      home();
      exit();
    }
    back();
    showFLog("浏览第：" + i + " 次");
    if (currentPackage() != "com.tencent.mm") {
      if (!widgetCheck("更多信息")) {
        log(currentPackage());
        exit();
      }
      showFLog("当前应用不是微信退出任务");
    }
  }
}

function 从下往上滑动(阅读文章速度) {
  log(arguments.callee.name + "开始");
  var 阅读文章速度 = 阅读文章速度 || 2.5;
  var w = device.width;
  var h = device.height;
  var x1 = Math.floor((w / 5) * 2);
  var y1 = Math.floor((h / 5) * 4);
  var x2 = Math.floor((w / 5) * 1);
  var y2 = Math.floor((h / 5) * 阅读文章速度);
  var duration = 300;
  log("滑动参数=", x1, y1, x2, y2, duration);
  swipeRnd(x1, y1, x2, y2, duration);
  log(arguments.callee.name + "结束");
  sleep(3000);
}
function swipeRnd(x1, y1, x2, y2, duration) {
  log(arguments.callee.name + "开始");
  var k = 20;
  var x1 = x1 + random(-k, k);
  var y1 = y1 + random(-k, k);
  var x2 = x2 + random(-k, k);
  var y2 = y2 + random(-k, k);
  var duration = duration + random(-k, k);
  swipeRnd2(x1, y1, x2, y2, duration);
}

function swipeRnd2(x1, y1, x2, y2, duration) {
  gesture(duration, [x1, y1], [x1 + 60, y1 - 80], [x2, y2]);
}

function clickView(obj) {
  try {
    let clickSuccessful = false;
    let originalObj = obj; // 保存最初的控件

    for (let i = 0; i < 4; i++) {
      if (obj && obj.clickable) {
        if (obj.click()) {
          clickSuccessful = true;
          break;
        }
      } else {
        obj = obj && obj.parent();
      }
    }
    clickSuccessful ? console.log("Control clicked successfully") : console.log("Control not clickable, checking parent");
    if (originalObj) {
      sleep(1000);
      log("开始校验控件点击后页面变换~~");
      let 第二校验 = className(originalObj.className())
        .depth(originalObj.depth())
        .boundsInside(originalObj.bounds().left, originalObj.bounds().top, originalObj.bounds().right, originalObj.bounds().bottom)
        .findOne(1000);
      if (第二校验) {
        console.log("校验不通过，位置点击");
        clickCenter(originalObj); // 点击最初的控件的中心位置
      }
    }
    sleep(500);
  } catch (error) {
    console.error("按键点击失败：" + error);
  }
}

function idAndClick(str, sleepTime) {
  sleepTime = sleepTime || 8000;
  let widgetGet = widgetGetById(str, sleepTime);
  if (widgetGet) {
    clickView(widgetGet);
    sleep(1000);
    return widgetGet;
  }
  return false;
}
function 找图(str, loop) {
  if (typeof loop === "undefined") {
    loop = 3;
  }
  findImageInRegion;
  var screen = images.captureScreen();
  screen = images.cvtColor(images.grayscale(screen), "GRAY2BGRA");
  var p = findImage(screen, images.fromBase64(str), { threshold: 0.6 });
  if (p) {
    toastLog("找到啦:" + p);
    let num = p.toString().replace(/{|}/g, "");
    let nums = num.split(",");
    click((nums[0] * 10) / 10, (nums[1] * 10) / 10);
    log("点击坐标：" + (nums[0] * 10) / 10 + " " + (nums[1] * 10) / 10);
    return true;
  } else if (loop-- > 1) {
    sleep(500);
    log("没查询到开始倒数第: b  " + loop + " 找图");
    return 找图(str, loop);
  } else {
    toastLog("没找到，找图失败");
    return false;
  }
}
function 打开微信页面() {
  log("打开微信");
  app.startActivity({
    className: "com.tencent.mm.ui.LauncherUI",
    packageName: "com.tencent.mm",
  });
  widgetGetOne("我");
  if (!idAndClick("com.tencent.mm:id/h6y")) {
    log("没查询到首页控件，返回2次");
    back();
    if (!widgetGetOne("我", 5000)) {
      back();
      if (!widgetGetOne("我", 5000)) {
        back();
      }
    }
    idAndClick("com.tencent.mm:id/h6y");
  }
  findAndClick("文件传输助手");
  input("<a href='http://h5.i90865zfdbh.cn/pipa_read?upuid=2822309' >可乐阅读入口</a>");

  sleep(1000);
  findAndClick("发送");
  sleep(1000);
  findAndClick("可乐阅读入口");
}
// 杀死后台
function killApp(appName) {
  //填写包名或app名称都可以
  var name = getPackageName(appName); //通过app名称获取包名
  app.openAppSetting(name); //通过包名打开应用的详情页(设置页)
  // sleep(3000); //稍微休息一下，不然看不到运行过程，自己用时可以删除这行
  if (findAndClick(/强.*|停.*|结.*/)) {
    findAndClick(/强.*|停.*|结.*/);
    findAndClick(/.*确.*|.*定.*/);
  }
  sleep(1000);
}

/**
 * 根据内容获取一个对象
 *
 * @param {string} contentVal
 * @param {number} timeout 默认超时时间5秒
 * @param {boolean} containType 是否带回类型
 * @param {boolean} suspendWarning 是否隐藏warning信息
 * @param {function} appendFilter 附加查询条件 详见UiSelector
 */
function widgetGetOne(contentVal, timeout, containType, suspendWarning, appendFilter, options) {
  let target = null;
  let isDesc = false;
  let waitTime = timeout || 8000;
  let timeoutFlag = true;
  showFLog(["try to find one: {} timeout: {}ms", contentVal.toString(), waitTime]);
  let checkResult = widgetCheck(contentVal, waitTime, true, appendFilter, options);
  if (!checkResult.timeout) {
    timeoutFlag = false;
    target = checkResult.target;
    isDesc = checkResult.isDesc;
  }
  // 当需要带回类型时返回对象 传递target以及是否是desc
  if (target && containType) {
    let result = {
      target: target,
      bounds: target.bounds(),
      isDesc: isDesc,
      content: isDesc ? target.desc() : target.text(),
    };
    return result;
  }
  return target;
}

/**
 * 替换控件搜索算法DFS,BFS,VDFS,VBFS,PDFS,PBFS,PVDFS,PVBFS
 * DFS,BFS为默认提供的深度优先和广度优先搜索算法
 * VDFS,VBFS为我修改的只搜索可见控件（控件包括父级不可见则直接跳过）深度优先和广度优先搜索算法 缺点是无法搜索不可见控件，适合一个界面中有巨量控件的时候用于加快搜索速度 实际数据抖音极速版从25s缩短到3s
 * PDFS,PBFS,PVDFS,PVBFS 是通过多线程搜索控件 大大加快搜索速度
 *
 * @param {string} algorithm 搜索算法DFS,BFS,VDFS,VBFS,PDFS,PBFS,PVDFS,PVBFS
 * @param {UiSelector} mselector
 * @returns
 */
function wrapSelector(algorithm, appendFilter, mselector) {
  appendFilter =
    appendFilter ||
    function (matcher) {
      return matcher;
    };
  mselector = appendFilter(mselector || selector());
  if (!algorithm) {
    return mselector;
  }
  // if (!algorithm_change_support) {
  //     log(['当前版本不支持替换搜索算法'])
  //     return mselector
  // }
  current = this.getCurrentAlgorithm();
  if (current == algorithm) {
    return mselector;
  }
  log(["替换搜索算法为：{} 原始算法：{}", algorithm, current]);
  return AlgorithmChanger.changeAlgorithm(mselector, algorithm);
}

/**
 * 查找一个子控件中的目标对象
 * @param {UiObject} container 父控件
 * @param {String} contentVal 控件文本
 * @param {number} timeout 超时时间 默认5秒
 * @param {Boolean} containType 返回结果附带文本是desc还是text
 * @param {function} appendFilter 附加查询条件 详见UiSelector
 * @param {Object} options 额外参数
 * 超时返回false
 */
function subWidgetGetOne(container, contentVal, timeout, containType, appendFilter, options) {
  options = options || {};
  timeout = timeout || 5000;
  let countDown = new java.util.concurrent.CountDownLatch(1);
  let matchRegex = new RegExp(contentVal);
  let isDesc = false;
  let isText = false;
  let target = null;
  let descThread = threads.start(function () {
    let descTarget = wrapSelector(options.algorithm, appendFilter).descMatches(matchRegex).findOneOf(container);
    if (descTarget) {
      log(["find desc {} {}", contentVal, descTarget.desc()]);
      isDesc = true;
      target = descTarget;
      countDown.countDown();
    }
  });

  let textThread = threads.start(function () {
    let textTarget = wrapSelector(options.algorithm, appendFilter).textMatches(matchRegex).findOneOf(container);
    if (textTarget) {
      log(["find text {} {}", contentVal, textTarget.text()]);
      isText = true;
      target = textTarget;
      countDown.countDown();
    }
  });

  let isTimeout = false;
  let timeoutThread = threads.start(function () {
    sleep(timeout);
    isTimeout = true;
    countDown.countDown();
  });

  countDown.await();
  descThread.interrupt();
  textThread.interrupt();
  timeoutThread.interrupt();
  if (isTimeout || (!isDesc && !isText)) {
    log("cannot find any matches " + contentVal);
  }
  if (target && containType) {
    return {
      isDesc: isDesc,
      target: target,
      bounds: target.bounds(),
      content: isDesc ? target.desc() : target.text(),
    };
  }
  return target;
}

/**
 * 查找一个子控件中的目标对象
 * @param {UiObject} container 父控件
 * @param {String} contentVal 控件id
 * @param {number} timeout 超时时间 默认5秒
 * @param {Boolean} containType 返回结果附带文本是desc还是text
 * @param {function} appendFilter 附加查询条件 详见UiSelector
 * @param {Object} options 额外参数
 * 超时返回false
 */
function subWidgetGetById(container, contentVal, timeout, containType, appendFilter, options) {
  options = options || {};
  timeout = timeout || 5000;
  let countDown = new java.util.concurrent.CountDownLatch(1);
  let matchRegex = new RegExp(contentVal);
  let isDesc = false;
  let isText = false;
  let target = null;
  let descThread = threads.start(function () {
    let descTarget = wrapSelector(options.algorithm, appendFilter).id(matchRegex).findOneOf(container);
    if (descTarget) {
      log(["find id {} {}", contentVal, descTarget.desc()]);
      isDesc = true;
      target = descTarget;
      countDown.countDown();
    }
  });

  let isTimeout = false;
  let timeoutThread = threads.start(function () {
    sleep(timeout);
    isTimeout = true;
    countDown.countDown();
  });

  countDown.await();
  descThread.interrupt();
  timeoutThread.interrupt();
  if (isTimeout || (!isDesc && !isText)) {
    log("cannot find any matches " + contentVal);
  }
  if (target && containType) {
    return {
      isDesc: isDesc,
      target: target,
      bounds: target.bounds(),
      content: isDesc ? target.desc() : target.text(),
    };
  }
  return target;
}

/**
 * 校验控件是否存在，并打印相应日志
 * @param {String} idRegex 控件文本
 * @param {String} position 日志内容 当前所在位置是否成功进入
 * @param {Number} timeoutSetting 超时时间 默认为 5秒
 */
function idWaiting(idRegex, position, timeoutSetting, appendFilter, options) {
  options = options || {};
  let waitingSuccess = idCheck(idRegex, timeoutSetting, false, appendFilter, options);
  position = position || idRegex;
  if (waitingSuccess) {
    log("等待控件成功：" + position);
    return true;
  } else {
    log("等待控件[" + position + "]失败， id：" + idRegex);
    return false;
  }
}

/**
 * id检测
 * @param {string|RegExp} idRegex
 * @param {number} timeoutSetting
 */
function idCheck(idRegex, timeoutSetting, containType, appendFilter, options) {
  options = options || {};
  let timeout = timeoutSetting || 5000;
  let timeoutFlag = true;
  let countDown = new java.util.concurrent.CountDownLatch(1);
  let target = null;
  let idCheckThread = threads.start(function () {
    target = wrapSelector(options.algorithm, appendFilter).idMatches(idRegex).findOne();
    log("find id " + idRegex);
    timeoutFlag = false;
    countDown.countDown();
  });

  let timeoutThread = threads.start(function () {
    sleep(timeout);
    countDown.countDown();
  });
  countDown.await();
  idCheckThread.interrupt();
  timeoutThread.interrupt();
  if (timeoutFlag) {
    log(["未能找到id:{}对应的控件", idRegex]);
  }
  if (containType) {
    return {
      timeout: timeoutFlag,
      target: target,
      bounds: target ? target.bounds() : null,
    };
  }
  return !timeoutFlag;
}

/**
 * 校验控件是否存在
 * @param {String} contentVal 控件文本
 * @param {Number} timeoutSetting 超时时间 单位毫秒
 * @param {Boolean} containType 返回结果附带文本是desc还是text
 * @param {Object} options 额外参数
 * 超时返回false
 */
function widgetCheck(contentVal, timeoutSetting, containType, appendFilter, options) {
  options = options || {};
  let timeout = timeoutSetting || 5000;
  let timeoutFlag = true;
  let countDown = new java.util.concurrent.CountDownLatch(1);
  let matchRegex = new RegExp(contentVal);
  let isDesc = false;
  let target = null;
  let descThread = threads.start(function () {
    target = wrapSelector(options.algorithm, appendFilter).descMatches(matchRegex).findOne();
    let res = target.desc();
    log("find desc " + contentVal + " " + res);
    timeoutFlag = false;
    isDesc = true;
    countDown.countDown();
  });

  let textThread = threads.start(function () {
    target = wrapSelector(options.algorithm, appendFilter).textMatches(matchRegex).findOne();
    let res = target.text();
    log("find text " + contentVal + "  " + res);
    timeoutFlag = false;
    countDown.countDown();
  });

  let timeoutThread = threads.start(function () {
    sleep(timeout);
    countDown.countDown();
  });
  countDown.await();
  descThread.interrupt();
  textThread.interrupt();
  timeoutThread.interrupt();
  if (timeoutFlag) {
    log("cannot find any matches " + contentVal + " timeout:" + timeout);
  }
  if (containType) {
    return {
      timeout: timeoutFlag,
      target: target,
      bounds: target ? target.bounds() : null,
      isDesc: isDesc,
    };
  }
  return !timeoutFlag;
}

/**
 * 校验控件是否存在，并打印相应日志
 * @param {String} contentVal 控件文本
 * @param {String} position 日志内容 当前所在位置是否成功进入
 * @param {Number} timeoutSetting 超时时间 单位毫秒 默认为_config.timeout_existing
 */
function widgetWaiting(contentVal, position, timeoutSetting, appendFilter, options) {
  options = options || {};
  let waitingSuccess = widgetCheck(contentVal, timeoutSetting, false, appendFilter, options);
  position = position || contentVal;
  if (waitingSuccess) {
    log("等待控件成功：" + position);
    return true;
  } else {
    log("等待控件[" + position + "]失败, 查找内容：" + contentVal);
    return false;
  }
}

/**
 * 根据id获取控件信息
 * @param {String|RegExp} idRegex id
 * @param {number} timeout 超时时间
 * @return 返回找到的控件，否则null
 */
function widgetGetById(idRegex, timeout, appendFilter, options) {
  options = options || {};
  timeout = timeout || 8000;
  let target = idCheck(idRegex, timeout, true, appendFilter, options);
  if (!target.timeout) {
    return target.target;
  } else {
    return null;
  }
}

function waitFor(action, timeout) {
  let countDown = new java.util.concurrent.CountDownLatch(1);
  let actionSuccess = false;
  let actionThread = null;
  let that = this;
  try {
    let start = new Date().getTime();
    actionThread = threads.start(function () {
      try {
        action();
        actionSuccess = true;
      } catch (e) {
        if (e.javaException instanceof com.stardust.autojs.runtime.exception.ScriptInterruptedException) {
          return;
        }
        warn("action执行异常" + e);
        that.printExceptionStack(e);
      } finally {
        countDown.countDown();
      }
      log(["action执行结束: {} 耗时：{}ms", actionSuccess, new Date().getTime() - start]);
    });
    let waitResult = countDown.await(timeout, java.util.concurrent.TimeUnit.MILLISECONDS);
    log(["waitFor方法执行完毕，action result: {}, wait result: {} cost time: {}ms", actionSuccess, waitResult, new Date().getTime() - start]);
    if (!waitResult) {
      log(["等待操作超时, 操作时间: {}ms", new Date().getTime() - start]);
    }
  } catch (e) {
    this.printExceptionStack(e);
  } finally {
    if (actionThread !== null) {
      actionThread.interrupt();
    }
  }
  return actionSuccess;
}

// let result = widgetUtils.alternativeWidget(/\s*今日签到\s*/, '.*明早7点可领.*', null, true)
// if (result.value === 1) {
/**
 * 判断控件A或者控件B是否存在；超时返回0 找到A返回1 否则返回2
 *
 * @param {string|regex} contentA 控件A的内容
 * @param {string|regex} contentB 控件B的内容
 * @param {number} timeout 超时时间
 * @param {boolean} containContent 是否传递实际内容
 * @param {function} appendFilter 附加查询条件 详见UiSelector
 * @param {object} options 额外参数
 * @return 超时返回0 找到A返回1 否则返回2
 */
function alternativeWidget(contentA, contentB, timeout, containContent, appendFilter, options) {
  options = options || {};
  timeout = timeout || _config.timeout_existing;
  let timeoutFlag = true;
  let countDown = new java.util.concurrent.CountDownLatch(1);
  let matchRegexA = new RegExp(contentA);
  let matchRegexB = new RegExp(contentB);
  let isDesc = false,
    findA = false;
  let res = null,
    target = null;
  let descThreadA = threads.start(function () {
    target = _this.wrapSelector(options.algorithm, appendFilter).descMatches(matchRegexA).findOne();
    res = target.desc();
    log("find desc " + contentA + " " + res);
    timeoutFlag = false;
    isDesc = true;
    findA = true;
    countDown.countDown();
  });

  let textThreadA = threads.start(function () {
    target = _this.wrapSelector(options.algorithm, appendFilter).textMatches(matchRegexA).findOne();
    res = target.text();
    log("find text " + contentA + "  " + res);
    timeoutFlag = false;
    findA = true;
    countDown.countDown();
  });
  let descThreadB = threads.start(function () {
    target = _this.wrapSelector(options.algorithm, appendFilter).descMatches(matchRegexB).findOne();
    res = target.desc();
    log("find desc " + contentB + " " + res);
    timeoutFlag = false;
    isDesc = true;
    countDown.countDown();
  });

  let textThreadB = threads.start(function () {
    target = _this.wrapSelector(options.algorithm, appendFilter).textMatches(matchRegexB).findOne();
    res = target.text();
    log("find text " + contentB + "  " + res);
    timeoutFlag = false;
    countDown.countDown();
  });

  let timeoutThread = threads.start(function () {
    sleep(timeout);
    countDown.countDown();
  });
  countDown.await();
  descThreadA.interrupt();
  textThreadA.interrupt();
  descThreadB.interrupt();
  textThreadB.interrupt();
  timeoutThread.interrupt();
  if (timeoutFlag) {
    log(["cannot find any matches {} or {}", contentA, contentB]);
  }
  // 超时返回0 找到A返回1 否则返回2
  let returnVal = timeoutFlag ? 0 : findA ? 1 : 2;
  if (containContent) {
    return {
      target: target,
      bounds: target ? target.bounds() : null,
      content: res,
      value: returnVal,
    };
  } else {
    return returnVal;
  }
}

// 快速打开("快手极速", "com.kuaishou.nebula", "com.yxcorp.gifshow.HomeActivity")
/**
 * 找到并且点击 如果返回错误就点击中心 返回一个布尔值
 * @param {str} 要找的字符串
 */
function findAndClick(str, sleepTime, waitsleep) {
  waitsleep = waitsleep || 100;
  sleepTime = sleepTime || 8000;
  sleep(waitsleep);
  let widgetGet = widgetGetOne(str, sleepTime);
  if (widgetGet) {
    clickView(widgetGet);
    sleep(1000);
    return widgetGet;
  }
  return false;
}
function clickCenter(obj) {
  sleep(400);
  log(obj.bounds().centerX() + " " + obj.bounds().centerY());
  click(obj.bounds().centerX(), obj.bounds().centerY());
}
function showFLog(msgLog) {
  let str = msgLog + " ";
  setInfo(str);
  log(msgLog);
}
//================悬浮窗开始================
function FloatyUtil() {
  this.floatyWindow = null;
  this.floatyInitStatus = false;
  this.floatyLock = threads.lock();
  this.floatyCondition = this.floatyLock.newCondition();
}

function init() {
  if (this.floatyInitStatus) {
    return;
  }
  let _this = this;
  threads.start(function () {
    _this.floatyLock.lock();
    try {
      if (_this.floatyInitStatus) {
        return;
      }
      _this.floatyWindow = floaty.rawWindow(
        <frame gravity="left">
          <text id="content" textSize="16dp" textColor="#00ff00" bg="#000000" />
        </frame>
      );
      ui.run(function () {
        _this.floatyWindow.setTouchable(false);
        _this.floatyWindow.setPosition(50, 50);
        _this.floatyWindow.content.text("悬浮窗初始化成功");
      });
      _this.floatyInitStatus = true;
    } catch (e) {
      console.error("悬浮窗初始化失败" + e);
      _this.floatyWindow = null;
      _this.floatyInitStatus = false;
    } finally {
      _this.floatyCondition.signalAll();
      _this.floatyLock.unlock();
    }
  });
  _this.floatyLock.lock();
  try {
    if (_this.floatyInitStatus === false) {
      console.info("等待悬浮窗初始化");
      _this.floatyCondition.await();
    }
  } finally {
    _this.floatyLock.unlock();
  }
}

function setInfo(text, position, option) {
  option = option || {};
  if (this.floatyWindow === null) {
    this.init();
  }
  let _this = this;
  ui.run(function () {
    _this.floatyLock.lock();
    try {
      if (position && isFinite(position.x) && isFinite(position.y)) {
        _this.floatyWindow.setPosition(parseInt(position.x), parseInt(position.y) + 100);
      }
      if (text) {
        _this.floatyWindow.content.text(text);
      }
      if (option.textSize) {
        _this.floatyWindow.content.setTextSize(option.textSize);
      }
      if (typeof option.touchable !== "undefined") {
        _this.floatyWindow.setTouchable(option.touchable);
      }
    } finally {
      _this.floatyLock.unlock();
    }
  });
}
//============悬浮窗结束=================
function 退出() {
  back();
  sleep(1000);
  back();
  sleep(1000);
  back();
  sleep(1000);
  home();
  exit();
}
